import re
from datetime import datetime
import numpy as np

# 读取日志文件
with open("./data/access_log_Aug95", "r", encoding="utf-8", errors="ignore") as f:
    logs = f.readlines()

# 1. 数据预处理
# 创建一个结构化数组存储提取的信息
log_dtype = np.dtype(
    [
        ("remote_addr", "U20"),  # 远程IP地址
        ("time_local", "datetime64[s]"),  # 请求时间
        ("request", "U100"),  # 请求路径
        ("status", "i4"),  # HTTP状态码
        ("body_bytes_sent", "i4"),  # 发送字节数
    ]
)
parsed_logs = np.zeros(len(logs), dtype=log_dtype)

# 正则表达式匹配日志行
log_pattern = re.compile(
    r'(?P<remote_addr>\S+) - - \[(?P<time_local>[^\]]+)\] "(?P<request>[^"]+)" (?P<status>\d{3}) (?P<body_bytes_sent>-|\d+)'
)

# 解析日志文件，提取关键信息
for i, log in enumerate(logs):
    match = log_pattern.match(log)

    if match:
        remote_addr = match.group("remote_addr")
        time_local_str = match.group("time_local")
        request = match.group("request")
        status = int(match.group("status"))
        body_bytes_sent = match.group("body_bytes_sent")
        body_bytes_sent = int(body_bytes_sent) if body_bytes_sent != "-" else 0

        # 去掉时区部分
        time_local_str = time_local_str[:-6]  # 去掉最后的时区信息（例如 -0400）

        # 解析日期和时间
        dt_object = datetime.strptime(time_local_str, "%d/%b/%Y:%H:%M:%S")

        parsed_logs[i] = (
            remote_addr,  # 远程IP地址
            np.datetime64(dt_object),  # 请求时间
            request,  # 请求路径
            status,  # HTTP状态码
            body_bytes_sent,  # 发送字节数
        )

# 2. 请求数量统计
# 提取日期信息
dates = np.array(parsed_logs["time_local"].astype("datetime64[D]"))
unique_dates, counts = np.unique(dates, return_counts=True)
print("每天请求数量：", dict(zip(unique_dates.astype(str), counts)))

# 3. 状态码分布
unique_status, status_counts = np.unique(parsed_logs["status"], return_counts=True)
print("状态码分布：", dict(zip(unique_status, status_counts)))

# 4. 访问峰值时间段
hours = np.array(parsed_logs["time_local"].astype("datetime64[h]")).astype(int) % 24
unique_hours, hour_counts = np.unique(hours, return_counts=True)

# 找到访问量最大的小时
peak_hour = unique_hours[np.argmax(hour_counts)]
print("访问峰值时间段：", peak_hour)

# 5. 每天访问量最大的小时段
print("\n每天访问量最大的小时段：")
for date in np.unique(dates):
    daily_hours = hours[dates == date]
    unique_daily_hours, daily_hour_counts = np.unique(daily_hours, return_counts=True)
    peak_hour = unique_daily_hours[np.argmax(daily_hour_counts)]
    print(f"{date.astype(str)}: {peak_hour} 点 - {daily_hour_counts.max()} 次请求")
